// promise 有三种状态，pedding,fulfilled, rejected，状态一旦改变就不会再次改变

const { resolve } = require("../../fed-e-002/codes/01-01-03-01-my-promise/myPromise");

// 
const PEDDING = 'pedding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
  constructor(executor) {
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }
  // promise 状态 初始化一开始的状态
  status = PEDDING
  value = undefined // 初始化成功之后的返回值
  err = undefined // 初始化失败后的值
  // 把有的成功/失败回调保存
  successCallback = []
  failCallback = []
  resolve = value => {
    // 检测状态不是等待，便阻止程序执行
    if(this.status !== PEDDING) {
      return 
    }
    this.status = FULFILLED // 将状态变更为成功
    this.value = value
    // 循环执行所有回调
    while(this.successCallback.length) this.successCallback.shift()(value)
  }
  reject = value => {
    // 检测状态不是等待，便阻止程序执行
    if(this.status !== PEDDING) {
      return 
    }
    this.status = REJECTED // 将状态变更为成功
    this.err = new Error('promise error')
    // 循环执行所有回调
    while(this.successCallback.length) this.successCallback.shift()(this.err)
  }
  then(successCallback, failCallback) {
    let promise2 = new MyPromise((resolve,reject) => {
      if(this.status === FULFILLED) {
        let last = successCallback(this.value) // 获取上一个回调的返回值作为参数
        resolve(last)
      } else if(this. status === REJECTED) {
        failCallback(this.err)
      } else {
        // 保存多次调用的回调函数
        this.successCallback.push(successCallback)
        this.failCallback.push(failCallback)
      }
    })
    return promise2
  }
  static all(array) {
    // console.log(array)
    let result = [] //保存执行结果
    let count = 0
    return new MyPromise((resolve, reject) => {
      function saveData(key,val) {
        result[key] = val
        count++
        if(count === array.length) {
          resolve(result)
        }
      }
      // 遍历array数组中的每一项，并将每一项保存在结果数组中
      for(let i = 0;i<array.length;i++) {
        // 需要判断当元素是否是 promise 对象
        if(array[i] instanceof MyPromise) {
          array[i].then(value => saveData(i,value), err => reject(err))
        } else {
          saveData(i,array[i])
        }
      }
      // resolve(result)
    })
  }
  // 模拟promise的resolve方法
  // 该方法返回一个promise对象
  static resolve (value) {
    // 首先判断参数是否是一个promise, 如果是：原样返回；不是：创建一个MyPromise对象并返回
    if(value instanceof MyPromise) return value
    return new MyPromise(resolve => resolve(value))
  }
  // 不管是否成功还是失败，都会执行该方法
  finally(callback) {
    return this.then(value => {
      callback()
      return value
    }, err => {
      callback()
      return err
    })
  }
}
module.exports = MyPromise